﻿/*
    创建日期: 2018.6.14
    创建者:张存
    邮箱:zhangcunliang@126.com
    说明：用于解析字节数组的帮助类
    修改记录:
        2019.8.8 使用偏移量初始化时 AnalyCount 未赋值的bug
 */
using System;
using System.Collections.Generic;
using System.Text;

namespace ASmile.Helpers
{
    public class BytesAnalyHelper
    {
        static BytesAnalyHelper()
        {
#if NETSTANDARD
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
#endif
        }

        /// <summary>
        /// 解析构造
        /// </summary>
        /// <param name="data">要解析的数据源</param>
        /// <param name="offset">数据源开始位置</param>
        /// <param name="count">数据源数量</param>
        /// <param name="skipCount">要跳过的字节数</param>
        public BytesAnalyHelper(byte[] data, int offset, int count, int skipCount)
        {
            _Data = new byte[count];
            Buffer.BlockCopy(data, offset, _Data, 0, count);
            _AnalyCount = skipCount;
        }
        /// <summary>
        /// 解析构造
        /// </summary>
        /// <param name="data">要解析的数据</param>
        /// <param name="skipCount">解析数据要跳过的字节数</param>
        public BytesAnalyHelper(byte[] data, int skipCount)
        {
            _Data = data;
            _AnalyCount = skipCount;
        }
        byte[] _Data;
        int _AnalyCount;  //已用该类解析的数组数

        /// <summary>
        /// 当前未解析的字节数
        /// </summary>
        public int NotAnalyCount
        {
            get
            {
                return _Data.Length - _AnalyCount;
            }
        }
        /// <summary>
        /// 跳过指定字节数
        /// </summary>
        public void SkipCount(int count)
        {
            _AnalyCount += count;
        }
        /// <summary>
        /// 获取剩余的字节数组
        /// </summary>
        /// <param name="bytesCount">当前要获取的字节数量</param>
        /// <param name="convertLH">是否高低位转换</param>
        /// <returns>返回字节数组</returns>
        public byte[] GetBytes(int bytesCount, bool convertLH = false)
        {
            byte[] rBytes = new byte[bytesCount];
            Buffer.BlockCopy(_Data, _AnalyCount, rBytes, 0, bytesCount);
            if (convertLH)
            {
                rBytes = BytesHelper.LittleToBigEndian(rBytes);
            }
            _AnalyCount += bytesCount;
            return rBytes;
        }
        /// <summary>
        /// 获取下一个字节内容
        /// </summary>
        /// <returns></returns>
        public byte GetByte()
        {
            var r = _Data[_AnalyCount];
            _AnalyCount++;
            return r;
        }
        /// <summary>
        /// 获取最后解析成16进制字符串
        /// </summary>
        public string GetHexString(int bytesCount, bool convertLH = false)
        {
            var b = GetBytes(bytesCount, convertLH);
            var hex = BytesHelper.ByteArrToHex(b, false);
            return hex;
        }

        /// <summary>
        /// 获取最后解析成字符串，GBK 编码转换
        /// </summary>
        /// <returns></returns>
        public string GetString(int bytesCount, bool convertLH = false)
        {
            if (bytesCount == 0) return string.Empty;
            return GetString(bytesCount, Encoding.GetEncoding("gbk"), convertLH);
        }
        /// <summary>
        /// 获取最后解析成字符串，指定编码转换 (不建议使用2021.6.30)
        /// </summary>
        public string GetString(int bytesCount, Encoding encode, bool convertLH = false)
        {
            var bs = GetBytes(bytesCount, convertLH);
            int count = bs.Length; //有效字符串的数量
            //for (int i = 0; i < bs.Length; i++)
            //{
            //    if (bs[i] == 0)
            //    {
            //        //第一个为0的后边所有内容为无效字符串，不能这么去掉 2021.6.30
            //        //注释这个会影响其它的解析
            //        count = i;
            //        break;
            //    }
            //}
            for (int i = bs.Length - 1; i >= 0; i--)
            {
                if (bs[i] != 0)
                {
                    //改为最后一个不为0的为数量（仍可能有问题，不建议 2021.6.30）
                    count = i + 1;
                    break;
                }
            }
            string rStr = encode.GetString(bs, 0, count);
            return rStr;
        }
        /// <summary>
        /// 指定编码的字符串获取 2021.6.30
        /// </summary>
        public string GetString(Encoding encode, int count, bool isTrim = true)
        {
            string rStr = encode.GetString(_Data, _AnalyCount, count);
            _AnalyCount += count;
            if (isTrim) return rStr.Trim();
            return rStr;
        }
        /// <summary>
        /// 得到下一个ushort值
        /// </summary>
        public ushort GetUInt16(bool convertLH = false)
        {
            var bs = GetBytes(2, convertLH);
            ushort r = BitConverter.ToUInt16(bs, 0);
            return r;
        }
        /// <summary>
        /// 得到下一个ushort值
        /// </summary>
        public short GetInt16(bool convertLH = false)
        {
            var bs = GetBytes(2, convertLH);
            short r = BitConverter.ToInt16(bs, 0);
            return r;
        }
        /// <summary>
        /// 得到下一个Int32值
        /// </summary>
        public uint GetUInt32(bool convertLH = false)
        {
            var bs = GetBytes(4, convertLH);
            var r = BitConverter.ToUInt32(bs, 0);
            return r;
        }
        /// <summary>
        /// 得到下一个Int32值
        /// </summary>
        public int GetInt32(bool convertLH = false)
        {
            var bs = GetBytes(4, convertLH);
            var r = BitConverter.ToInt32(bs, 0);
            return r;
        }
        /// <summary>
        /// 得到下一个uInt64值
        /// </summary>
        public ulong GetUInt64(bool convertLH = false)
        {
            var bs = GetBytes(8, convertLH);
            var r = BitConverter.ToUInt64(bs, 0);
            return r;
        }
        /// <summary>
        /// 得到下一个Int64值
        /// </summary>
        public long GetInt64(bool convertLH = false)
        {
            var bs = GetBytes(8, convertLH);
            var r = BitConverter.ToInt64(bs, 0);
            return r;
        }
        /// <summary>
        /// 获取浮点类型
        /// </summary>
        public float GetFloat(bool convertLH = false)
        {
            var bs = GetBytes(4, convertLH);
            var r = BitConverter.ToSingle(bs, 0);
            return r;
        }
        /// <summary>
        /// 获取双精度浮点
        /// </summary>
        /// <param name="convertLH">是否进行高低位转换</param>        
        public double GetDouble(bool convertLH = false)
        {
            var bs = GetBytes(8, convertLH);
            var r = BitConverter.ToDouble(bs, 0);
            return r;
        }
        /// <summary>
        /// 获取IP地址字符串
        /// </summary>
        /// <returns></returns>
        public string GetIpString(bool convertLH = false)
        {
            var bs = GetBytes(4, convertLH);
            var r = string.Format("{0}.{1}.{2}.{3}", bs[0], bs[1], bs[2], bs[3]);
            return r;
        }

        /// <summary>
        /// 16进制转换BCD（单个解压BCD）
        /// </summary>
        public byte GetBCD()
        {
            var bs = GetByte();
            //高四位  
            byte bh = (byte)(bs / 10);
            //低四位  
            byte bl = (byte)(bs % 10);
            return (byte)((bh << 4) | bl);
        }
    }
}